package br.usp.ime.macmovel.android;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.RatingBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

/**
 * This class can show and register current line, food quality and menu of bandex restaurants. 
 */
public class BandexActivity extends Activity {
	private int last_bandex_selected;
	private TextView queue_time_msg;
	private RatingBar submitted_food_score;
	private String[] bandex_list;
	private String bandex;
	private int[] minutes_list;
	private int minutes;
	private int score;
	private TextView unavailable_score;
	private DateProvider date_provider;
	
	/**
	 * Initial setup when no information has been retrieved yet.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.bandex);
		
		Resources res = getResources();
		bandex_list = res.getStringArray(R.array.bandex_array);
		minutes_list = res.getIntArray(R.array.minutes_array);
		date_provider = new DateProvider();
				
		last_bandex_selected = -1;
		minutes = -1;
		score = -1;
		
		configureLayout();
	}
	
	/**
	 * Reminds users to participate by submitting line times and votes on food quality.
	 */
    @Override
    protected void onResume() {
    	Toast.makeText(BandexActivity.this, getString(R.string.user_participation), Toast.LENGTH_LONG).show();
    	super.onResume();
    }

    /**
     * Updates the line size and food quality for the currently selected restaurant.
     */
	private void updateMinutesAndScore() {
		String queue_time_message;
		
		String url = getString(R.string.base_bandex_server_url);
		url += getString(R.string.bandex_server_query);
		url += getString(R.string.bandex_server_name);
		url += bandex;
				
		HttpClient httpclient = new DefaultHttpClient();
   	 	HttpGet httpget = new HttpGet(url);
   	 	try {
			HttpResponse response = httpclient.execute(httpget);
	        BufferedReader in = new BufferedReader
            (new InputStreamReader(response.getEntity().getContent()));
	        score = new Scanner(in.readLine()).useDelimiter("[^-0-9]+").nextInt();
	        minutes = new Scanner(in.readLine()).useDelimiter("[^-0-9]+").nextInt();
            in.close();
		} catch (Exception e) {
			Toast.makeText(BandexActivity.this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show();
			e.printStackTrace();
		}
		
	    queue_time_message = "";
		if (minutes != -1) {
		    queue_time_message += minutes;
		    queue_time_message += getString(R.string.queue_time_min);
		}
		else {
			queue_time_message += getString(R.string.Unavailable);
		}
		
	    queue_time_msg.setText(queue_time_message);
	    
	    if (score != -1) {
	    	submitted_food_score.setRating(score);
	    	unavailable_score.setVisibility(View.GONE);
	    	submitted_food_score.setVisibility(View.VISIBLE);
	    }
	    else {
	    	submitted_food_score.setVisibility(View.GONE);
	    	unavailable_score.setVisibility(View.VISIBLE);
	    }
	}

	/**
	 * Sets up the defined layout for the app.
	 */
	private void configureLayout() {
		Spinner bandex_spinner = (Spinner) findViewById(R.id.restaurants_spinner);
		configureBandexSpinner(bandex_spinner);
	    
	    queue_time_msg = (TextView) findViewById(R.id.queue_time);
	    
	    submitted_food_score = (RatingBar) findViewById(R.id.submitted_food_score);
	    submitted_food_score.setEnabled(false);
	    
	    unavailable_score = (TextView) findViewById(R.id.unavailable_score);
	    
	    Button update_bandex_info = (Button) findViewById(R.id.update_bandex_info);
	    configureUpdateButton(update_bandex_info);
	    
	    Spinner queue_time_spinner = (Spinner) findViewById(R.id.queue_time_spinner);
	    configureQueueTimeSpinner(queue_time_spinner);
	    
	    Button submit_food_score = (Button) findViewById(R.id.submit_food_score);
	    configureFoodScoreButton(submit_food_score);
	    
	    Button submit_queue_time = (Button) findViewById(R.id.submit_queue_time);
	    configureQueueTimeButton(submit_queue_time);
	    
		RatingBar score_given = (RatingBar) findViewById(R.id.food_score_rating_bar);
		score_given.setRating(1.0f);
	}
	
	/**
	 * Gets the menu for the day and meal (lunch or dinner) of the currently selected restaurant.
	 */
	private void updateMeals() {
		int hours = date_provider.getHours();
		
		TextView cardapio = (TextView) findViewById(R.id.cardapio);
		
		String url = getString(R.string.base_bandex_server_url);
		url += getString(R.string.bandex_server_menu);
		url += getString(R.string.bandex_server_name);
		url += bandex;
		url += getString(R.string.bandex_server_day);
		url += date_provider.getDayOfWeek();
		
		String message;
		
		if (hours > 15) {
			url += getString(R.string.bandex_server_dinner);
		}
				
		HttpClient httpclient = new DefaultHttpClient();
   	 	HttpGet httpget = new HttpGet(url);
   	 	try {
			HttpResponse response = httpclient.execute(httpget);
	        HttpEntity entity = response.getEntity();
	        message = EntityUtils.toString(entity);
   	 	} catch (Exception e) {
			Toast.makeText(BandexActivity.this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show();
			message = getString(R.string.Unavailable);
			e.printStackTrace();
		}
		
   	 	cardapio.setText(message);
	}
	
	/**
	 * Updates the information (line, quality) when button is clicked.
	 */
	private void configureUpdateButton(Button update_bandex_info) {
		update_bandex_info.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				updateMinutesAndScore();
				updateMeals();
			}
		});
	}

	/**
	 * Submits a line time for the restaurant selected.
	 */
	private void configureQueueTimeButton(Button submit_queue_time) {
		submit_queue_time.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				Spinner queue_time_selected = (Spinner) findViewById(R.id.queue_time_spinner);
				int pos = queue_time_selected.getSelectedItemPosition();
				
				String url = getString(R.string.base_bandex_server_url);
				url += getString(R.string.bandex_server_register);
				url += getString(R.string.bandex_server_name);
				url += bandex;
				url += getString(R.string.bandex_server_line);
				url += minutes_list[pos];
						
				HttpClient httpclient = new DefaultHttpClient();
		   	 	HttpGet request = new HttpGet(url);
		   	 	try {
					httpclient.execute(request);
					Toast.makeText(BandexActivity.this, getString(R.string.info_submitted), Toast.LENGTH_SHORT).show();
				} catch (Exception e) {
					Toast.makeText(BandexActivity.this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show();
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Sets up the star system for food quality GUI.
	 */
	private void configureFoodScoreButton(Button submit_food_score) {
		submit_food_score.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				RatingBar score_given = (RatingBar) findViewById(R.id.food_score_rating_bar);
				int rating = (int) score_given.getRating();
				
				String url = getString(R.string.base_bandex_server_url);
				url += getString(R.string.bandex_server_register);
				url += getString(R.string.bandex_server_name);
				url += bandex;
				url += getString(R.string.bandex_server_score);
				url += (int) rating;
						
				HttpClient httpclient = new DefaultHttpClient();
		   	 	HttpGet request = new HttpGet(url);
		   	 	try {
					httpclient.execute(request);
					Toast.makeText(BandexActivity.this, getString(R.string.info_submitted), Toast.LENGTH_SHORT).show();
				} catch (Exception e) {
					Toast.makeText(BandexActivity.this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show();
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Sets up the spinner to select the time in line to be submitted to the server.
	 */
	private void configureQueueTimeSpinner(Spinner queue_time_spinner) {
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
	            this, R.array.times_array, android.R.layout.simple_spinner_item);
	    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	    queue_time_spinner.setAdapter(adapter);	
	}

	/**
	 * Sets up the spinner to choose the bandex.
	 */
	private void configureBandexSpinner(Spinner bandex_spinner) {
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
	            this, R.array.bandex_array, android.R.layout.simple_spinner_item);
	    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	    bandex_spinner.setAdapter(adapter);
	    
	    bandex_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> parent, View view,
					int pos, long id) {
				if (pos != last_bandex_selected){
					last_bandex_selected = pos;
					bandex = bandex_list[pos];
					updateMinutesAndScore();
					updateMeals();
				}
			}

			public void onNothingSelected(AdapterView<?> parent) {
				
			}
		});
	}
	
	/**
	 * Sets the DateProvider used to get current time, date etc.
	 */
	public void setDateProvider(DateProvider dateProvider) {
		date_provider = dateProvider;
	}
	
}